#include <cahumsat_planner/CAHUMSAT_PlannerE.h>
#include <iostream>
using namespace std;
// ***********************************************************************

// class EDROOMTopContext

// ***********************************************************************



	// CONSTRUCTORES***********************************************

CAHUMSAT_Planner::EDROOMTopContext::EDROOMTopContext (CAHUMSAT_Planner &act, bool & EDROOMpVarVSGIActive, bool & EDROOMpVarVSGIEnd, bool & EDROOMpVarVSSIActive, bool & EDROOMpVarVSSIEnd, CEDROOMPOOLCDCommConfig & EDROOMpPoolCDCommConfig ):

	EDROOMcomponent(act)
	,Msg(EDROOMcomponent.Msg)
	,MsgBack(EDROOMcomponent.MsgBack)
	,PlannerHousek(EDROOMcomponent.PlannerHousek)
	,SSICtrl(EDROOMcomponent.SSICtrl)
	,SGIControl(EDROOMcomponent.SGIControl)
	,Timer(EDROOMcomponent.Timer)
	, VSGIActive ( EDROOMpVarVSGIActive )
	, VSGIEnd ( EDROOMpVarVSGIEnd )
	, VSSIActive ( EDROOMpVarVSSIActive )
	, VSSIEnd ( EDROOMpVarVSSIEnd )
	, CEDROOMPoolCDCommConfig ( EDROOMpPoolCDCommConfig )
 {

}

CAHUMSAT_Planner::EDROOMTopContext::EDROOMTopContext ( EDROOMTopContext &contex ):

	EDROOMcomponent(contex.EDROOMcomponent),
	Msg(contex.Msg),
	MsgBack(contex.MsgBack)
	,PlannerHousek(contex.PlannerHousek)
	,SSICtrl(contex.SSICtrl)
	,SGIControl(contex.SGIControl)
	,Timer(contex.Timer)
	, VSGIActive ( contex.VSGIActive )
	, VSGIEnd ( contex.VSGIEnd )
	, VSSIActive ( contex.VSSIActive )
	, VSSIEnd ( contex.VSSIEnd )
	, CEDROOMPoolCDCommConfig ( contex.CEDROOMPoolCDCommConfig )
 {

}

	// EDROOMSearchContextTrans********************************************

bool CAHUMSAT_Planner::EDROOMTopContext::EDROOMSearchContextTrans(TEDROOMTransId &edroomCurrentTrans){

	bool edroomValidMsg=false; 

	 switch(Msg->signal){

		 case ( EDROOMSignalDestroy ): 

			 edroomValidMsg=true;
			 edroomCurrentTrans.distanceToContext = 0 ;
			 edroomCurrentTrans.localId = -1 ;
			 break;

	}

	return(edroomValidMsg);

}

	// Funciones Definidas por el usuario  ****************************

void	CAHUMSAT_Planner::EDROOMTopContext::FIni()

{
 cout<<"Entro en el Planner"<<endl;
 CUniTime::Init();
 
 
 
}



void	CAHUMSAT_Planner::EDROOMTopContext::FProgSwWatchDog()

{
 
		// Timing Service 
	 
			//Useful related methods
			 
			//Pr_Time	interval(Pr_Time::millis,int); // Declare time var with an initial value in ms
			//Pr_Time	interval(Pr_Time::micros,int); // Declare time var with an initial value in microseg
			Pr_Time	interval(1.0); // Declare time var with an initial value in seconds
	 
	Timer.InformIn( interval, EDROOMprioVeryHigh );
 
 
 
 
}



void	CAHUMSAT_Planner::EDROOMTopContext::FCommProg()

{
 cout<<"Entro en Planner:FCommProg"<<endl;
 
 Pr_Time currentTime;
 currentTime.GetTime();
 //cout<<currentTime.Secns()<<endl;
 
 CUniTime time;
 time.SetWithCurrentUniTime();
 time.TraceUniTime();
 
 CHUMSATCommManager temp;
 HUMSATCommProg_t commProg1;
 
 temp.InitHUMSATCommProgTable();
 temp.GetNextHUMSATCommProg(commProg1);

 cout<<"Siguiente elemento de la tabla: "<<commProg1.init_time.GetUniTimeSeconds()<<" Tiempo de fin de la tabla: "<<commProg1.end_time.GetUniTimeSeconds()<<endl;;
 
  if (temp.IsHUMSATCommValid(commProg1)){
        VSSIActive=false;
        VSGIActive=false;
        
        if ((commProg1.init_time.GetUniTimeSeconds())==(CUniTime::GetCurrentUniTimeSeconds())){
     
        if(commProg1.txrxConfig==00000000){
        cout<<">>>>>>>>>>>>>>>>>>>>>>>>>Empieza SSI"<<endl;
        VSSIActive=true;
        }

        if(commProg1.txrxConfig==00000001){
        cout<<">>>>>>>>>>>>>>>>>>>>>>>>>Empieza SGI"<<endl;
        VSGIActive=true;
        }
 }
 
        if ((commProg1.end_time.GetUniTimeSeconds())==(CUniTime::GetCurrentUniTimeSeconds())){
        VSSIActive=false;
        VSGIActive=false;

        if(commProg1.txrxConfig==00000000){
        VSSIEnd=true;
        }

        if(commProg1.txrxConfig==00000001){
        cout<<">>>>>>>>>>>>>>>>>>>>>>>>>Empieza SGI"<<endl;
        VSGIEnd=true;
        }
 }

}
}


void	CAHUMSAT_Planner::EDROOMTopContext::FSGIEnd()

{
cout<<"Entro en Planner:FSGIEnd"<<endl;
 VSGIEnd=false;
		// invoke 
	
	MsgBack=PlannerHousek.invoke(SEndSGIComm, EDROOMprioVeryHigh);
	
		// Handling MsgBack
	
	
	
	
		// End Handling MsgBack
	
	EDROOMFreeMsgBack(MsgBack);
 
}



void	CAHUMSAT_Planner::EDROOMTopContext::FSGIStart()

{cout<<"Entro en Planner:FSGIStart"<<endl;
 
		// invoke 
	
	MsgBack=PlannerHousek.invoke(SStartSGIComm, EDROOMprioVeryHigh);
	
		// Handling MsgBack
	
	
	
	
		// End Handling MsgBack
	
	EDROOMFreeMsgBack(MsgBack);

		// invoke 
	
	MsgBack=SGIControl.invoke(SToComm, EDROOMprioVeryHigh);
	
		// Handling MsgBack
	
	
	
	
		// End Handling MsgBack
	
	EDROOMFreeMsgBack(MsgBack);

 
}



void	CAHUMSAT_Planner::EDROOMTopContext::FSSIEnd()

{VSSIEnd=false;
cout<<"Entro en Planner: FSSIEnd"<<endl;
 
		// invoke 
	
	MsgBack=PlannerHousek.invoke(SEndSSIComm, EDROOMprioVeryHigh);
	
		// Handling MsgBack
	
	
	
	
		// End Handling MsgBack
	
	EDROOMFreeMsgBack(MsgBack);
 
		// send new Msg
	
	SSICtrl.send(SToListening, EDROOMprioNormal);

}



void	CAHUMSAT_Planner::EDROOMTopContext::FSSIStart()

{cout<<"Entro en Planner: FSSIStart"<<endl;
 
		// invoke 
	
	MsgBack=PlannerHousek.invoke(SStartSSIComm, EDROOMprioVeryHigh);
	
		// Handling MsgBack
	
	
	
	
		// End Handling MsgBack
	
	EDROOMFreeMsgBack(MsgBack);
		// send new Msg
	
	SSICtrl.send(SToListening, EDROOMprioNormal);
 
}



TEDROOMBool	CAHUMSAT_Planner::EDROOMTopContext::GStartSGI()

{
return VSGIActive;
 
 
}



TEDROOMBool	CAHUMSAT_Planner::EDROOMTopContext::GStartSSI()

{
return VSSIActive;
}



void	CAHUMSAT_Planner::EDROOMTopContext::FEndComm()

{
 cout<<"Entro en Planner: FEndComm"<<endl;

		// send new Msg
	
	SGIControl.send(SToStandBy, EDROOMprioNormal);
 
 
 
 
}



void	CAHUMSAT_Planner::EDROOMTopContext::FKeepOnComm()

{
 cout<<"Entro en planner: FKeepOnComm"<<endl;

		// invoke 
	
	MsgBack=SGIControl.invoke(SKeepOnComm, EDROOMprioVeryHigh);
	
		// Handling MsgBack
	
	
	
	
		// End Handling MsgBack
	
	EDROOMFreeMsgBack(MsgBack);
	

 
 
 
 
}



TEDROOMBool	CAHUMSAT_Planner::EDROOMTopContext::GEndSGI()

{
 if (VSGIEnd==true){
    cout<<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Acaba de terminar SGI"<<endl;
    VSGIActive=false;
}
return VSGIEnd; 
 
 
 
}



TEDROOMBool	CAHUMSAT_Planner::EDROOMTopContext::GEndSSI()

{
 if (VSSIEnd==true){
    cout<<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Acaba de terminar SSI"<<endl;
    VSGIActive=false;
}
return VSSIEnd; 
 
 
 
}



	//*****Pools

	//CEDROOMPOOLCDCommConfig

CAHUMSAT_Planner::EDROOMTopContext::CEDROOMPOOLCDCommConfig::CEDROOMPOOLCDCommConfig(unsigned int elemCount, CDCommConfig* pMem, TEDROOMBool * pMemMarks):CEDROOMProtectedMemoryPool(elemCount, pMem, pMemMarks, sizeof (CDCommConfig)){;}

CDCommConfig *	CAHUMSAT_Planner::EDROOMTopContext::CEDROOMPOOLCDCommConfig::AllocData(){
	return(CDCommConfig*)CEDROOMProtectedMemoryPool::AllocData();
}



// ***********************************************************************

// class EDROOMTopState

// ***********************************************************************



	// CONSTRUCTOR*************************************************

CAHUMSAT_Planner::EDROOMTopState::EDROOMTopState (CAHUMSAT_Planner &act, CEDROOMMemory *pEDROOMMemory  ):
	  EDROOMTopContext( act , VSGIActive, VSGIEnd, VSSIActive, VSSIEnd,CEDROOMPoolCDCommConfig )
	, VSGIActive ( false )
	, VSGIEnd ( false )
	, VSSIActive ( false )
	, VSSIEnd ( false )
	, CEDROOMPoolCDCommConfig ( 10, pEDROOMMemory->poolCDCommConfig, pEDROOMMemory->poolMarkCDCommConfig)
{

}

	// EDROOMBehaviour**********************************************

void CAHUMSAT_Planner::EDROOMTopState::EDROOMBehaviour(){

	TEDROOMTransId edroomCurrentTrans;

	edroomCurrentTrans = EDROOMIllegada();

	do{

		switch(edroomCurrentTrans.localId){

			case(Init):
				FIni();
				edroomNextState = Ready;
				break;
			case(Timeout):
				FCommProg();

				EDROOMcomponent.EDROOMTraceStateEntry();

				if( GEndSSI() ){
					FSSIEnd();
					edroomCurrentTrans.localId = Timeout_EndSSI;
					edroomNextState = Ready;
				 } 
				else if( GEndSGI() ){
					FSGIEnd();
					edroomCurrentTrans.localId = Timeout_EndSGI;
					edroomNextState = Ready;
				 } 
				else if( GStartSGI() ){
					FSGIStart();
					edroomCurrentTrans.localId = Timeout_StartSGI;
					edroomNextState = Ready;
				 } 
				else if( GStartSSI() ){
					FSSIStart();
					edroomCurrentTrans.localId = Timeout_StartSSI;
					edroomNextState = Ready;
				 } 
				else{
					edroomCurrentTrans.localId = Timeout_NoCommProg;
					edroomNextState = Ready;
				 } 
				EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);
				break;
			case(CommInterrupted):

				EDROOMcomponent.EDROOMTraceStateEntry();

				if( VSGIActive ){
					FKeepOnComm();
					edroomCurrentTrans.localId = CommInterrupted_SGIActive;
					edroomNextState = Ready;
				 } 
				else{
					FEndComm();
					edroomCurrentTrans.localId = CommInterrupted_EndComm;
					edroomNextState = Ready;
				 } 
				EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);
				break;
		}

		EDROOMcomponent.EDROOMTraceStateEntry();

		EDROOMcomponent.EDROOMTraceStateEntry();

		switch(edroomNextState){

			case(I):
				edroomCurrentTrans=EDROOMIllegada();
				break;

			case(Ready):
				FProgSwWatchDog();
				edroomCurrentTrans=EDROOMReadyllegada();
				break;

		}

		EDROOMcomponent.EDROOMTraceStateExit();

		edroomCurrentState=edroomNextState;

	}while(Msg->signal != EDROOMSignalDestroy);

}



	// Inicio**********************************************

void CAHUMSAT_Planner::EDROOMTopState::EDROOMInicio(){

edroomCurrentState=I;

}



//	 ***********************************************************************

//	 llegada SubEstado I

//	 ***********************************************************************



TEDROOMTransId CAHUMSAT_Planner::EDROOMTopState::EDROOMIllegada(){

	TEDROOMTransId edroomCurrentTrans;

	edroomCurrentTrans.localId = Init;
	edroomCurrentTrans.distanceToContext = 0;
	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, 0);

	return(edroomCurrentTrans);

}



	// ***********************************************************************

	// llegada SubEstado Hoja Ready

	// ***********************************************************************



TEDROOMTransId CAHUMSAT_Planner::EDROOMTopState::EDROOMReadyllegada(){

	TEDROOMTransId edroomCurrentTrans;

	int edroomValidMsg=false;

	do{

		EDROOMNuevoMens ();

		switch(Msg->signal){

			case (EDROOMSignalTimeout): 

				 if ( *Msg->GetPInterface() == Timer) {

					edroomCurrentTrans.localId = Timeout;
					edroomCurrentTrans.distanceToContext = 0 ;
					edroomValidMsg=true;
				 }

				break;

			case (SCommInterrupted): 

				 if ( *Msg->GetPInterface() == SGIControl) {

					edroomCurrentTrans.localId = CommInterrupted;
					edroomCurrentTrans.distanceToContext = 0 ;
					edroomValidMsg=true;
				 }

				break;

		};

		if (!edroomValidMsg) edroomValidMsg = EDROOMSearchContextTrans(edroomCurrentTrans);

	} while (!edroomValidMsg);

	EDROOMcomponent.EDROOMTraceTrans(edroomCurrentTrans, Msg->signal);

	return(edroomCurrentTrans);

}



